package com.example.permission.service.impl;

import cn.hutool.core.convert.Convert;
import com.example.permission.common.CommonParam;
import com.example.permission.common.Constants;
import com.example.permission.common.page.Page;
import com.example.permission.common.result.Result;
import com.example.permission.common.utils.JwtUtil;
import com.example.permission.common.utils.NetworkUtil;
import com.example.permission.entity.dto.LoginDTO;
import com.example.permission.entity.dto.PasswordDTO;
import com.example.permission.entity.dto.SysUserDTO;
import com.example.permission.entity.dto.page.SysUserPageDTO;
import com.example.permission.entity.po.SysAct;
import com.example.permission.entity.po.SysLoginLog;
import com.example.permission.entity.po.SysUser;
import com.example.permission.entity.vo.SysAclVO;
import com.example.permission.entity.vo.SysActVO;
import com.example.permission.enums.DataStatusEnum;
import com.example.permission.enums.TokenTypeEnum;
import com.example.permission.mapper.SysAclMapper;
import com.example.permission.mapper.SysActMapper;
import com.example.permission.mapper.SysLoginLogMapper;
import com.example.permission.mapper.SysUserMapper;
import com.example.permission.service.SysUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 用户信息表(SysUser)表服务实现类
 *
 * @author xuwq
 * @date 2020-05-09 15:56:07
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class SysUserServiceImpl implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private SysLoginLogMapper loginLogMapper;
    @Autowired
    private HttpServletRequest request;
    @Autowired
    private SysActMapper sysActMapper;
    @Autowired
    private SysAclMapper sysAclMapper;
    @Value("${reset.password:}")
    private String resetPassword;


    @Override
    public Result<Map<String, Object>> login(LoginDTO loginDTO) {
        String ipAddress = NetworkUtil.getIpAddress(request);
        String imageCodeOld = (String) redisTemplate.opsForValue().get(Constants.IMG_IDENTIFY_CODE + ipAddress);
        if (StringUtils.isBlank(imageCodeOld)) {
            return Result.fail("图形验证码错误，请重新输入");
        }
        if (!imageCodeOld.equals(loginDTO.getImageCode())) {
            return Result.fail("图形验证码错误，请重新输入");
        }
        SysUser sysUser = sysUserMapper.queryByUserNo(loginDTO.getUserNo());
        if (sysUser == null) {
            return Result.fail("用户不存在");
        }
        SysLoginLog sysLoginLog = new SysLoginLog();
        sysLoginLog.setUserNo(sysUser.getUserNo());
        sysLoginLog.setUserName(sysUser.getUserName());
        sysLoginLog.setIp(ipAddress);
        sysLoginLog.setLoginLocation(request.getRequestURI());
        sysLoginLog.setBrowser(NetworkUtil.getBrowserName(request) + " " + NetworkUtil.getBrowserVersion(request));
        sysLoginLog.setOs(NetworkUtil.getOsName(request));
        sysLoginLog.setLoginTime(new Date());
        if (!sysUser.getPassword().equals(loginDTO.getPassword())) {
            //登陆失败
            sysLoginLog.setDataStatus(2);
            sysLoginLog.setRemark("密码错误");
            loginLogMapper.insert(sysLoginLog);
            return Result.fail("账号或密码错误");
        }
        Map<String, String> map = new HashMap<>();
        map.put("userId", Convert.toStr(sysUser.getUserId()));
        map.put("userNo", sysUser.getUserNo());
        map.put("tokenType", TokenTypeEnum.USER.getCode());
        String token = JwtUtil.genToken(map);
        redisTemplate.opsForValue().set(Constants.USER_TOKEN + sysUser.getUserNo(), token, 30, TimeUnit.MINUTES);
        //登陆成功
        sysLoginLog.setDataStatus(1);
        loginLogMapper.insert(sysLoginLog);
        //用户角色
        List<SysActVO> sysActVOList = sysActMapper.queryListByUserId(sysUser.getUserId());
        String roleIds = sysActVOList.stream().map(SysAct::getRoleId).map(Object::toString).collect(Collectors.joining(","));
        //用户菜单
        List<SysAclVO> sysAclVOList = sysAclMapper.queryListByRoleIds(roleIds);
        Map<String, Object> loginMap = new HashMap<>();
        loginMap.put("sysUser", sysUser);
        loginMap.put("roleList", sysActVOList);
        loginMap.put("menuList", sysAclVOList);
        loginMap.put("token", token);
        return Result.success(loginMap);
    }

    @Override
    public SysUser insert(SysUserDTO sysUserDTO) {
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(sysUserDTO, sysUser);
        sysUser.setCreateTime(new Date());
        sysUser.setCreator(CommonParam.getInstance().getUserNo());
        this.sysUserMapper.insert(sysUser);
        return sysUser;
    }

    @Override
    public SysUser update(SysUserDTO sysUserDTO) {
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(sysUserDTO, sysUser);
        sysUser.setUpdateTime(new Date());
        sysUser.setUpdator(CommonParam.getInstance().getUserNo());
        this.sysUserMapper.update(sysUser);
        return this.queryById(sysUser.getUserId());
    }

    @Override
    public boolean deleteById(Integer userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setDataStatus(DataStatusEnum.ABNORMAL.getCode());
        return this.sysUserMapper.update(sysUser) > 0;
    }

    @Override
    public SysUser queryById(Integer userId) {
        return this.sysUserMapper.queryById(userId);
    }

    @Override
    public Page<SysUser> queryListByPage(SysUserPageDTO sysUserPageDTO) {
        int count = this.sysUserMapper.queryCountByPage(sysUserPageDTO);
        List<SysUser> sysUserList = this.sysUserMapper.queryListByPage(sysUserPageDTO);
        return new Page<>(count, sysUserList);
    }

    @Override
    public void roleDistribution(Integer userId, String roleIds) {
        //先删除，再插入
        sysActMapper.deleteByUserId(userId);
        Arrays.stream(roleIds.split(",")).forEach(c -> {
            SysAct sysAct = new SysAct();
            sysAct.setUserId(userId);
            sysAct.setRoleId(Convert.toInt(c));
            sysActMapper.insert(sysAct);
        });
    }

    @Override
    public List<SysActVO> queryRolesByUserId(Integer userId) {
        return sysActMapper.queryListByUserId(userId);
    }

    @Override
    public List<SysAclVO> queryMenusByRoleIds(String roleIds) {
        return sysAclMapper.queryListByRoleIds(roleIds);
    }

    @Override
    public void resetPassword(Integer userId) {
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setPassword(resetPassword);
        sysUser.setUpdateTime(new Date());
        sysUser.setUpdator(CommonParam.getInstance().getUserNo());
        sysUserMapper.update(sysUser);
    }

    @Override
    public Result forgetPassword(Integer userId, PasswordDTO passwordDTO) {
        SysUser sysUser = sysUserMapper.queryById(userId);
        if (sysUser == null) {
            return Result.fail("用户不存在");
        }
        if (!passwordDTO.getOldPassword().equals(sysUser.getPassword())) {
            return Result.fail("旧密码错误");
        }
        if (!passwordDTO.getPassword().equals(passwordDTO.getAgainPassword())) {
            return Result.fail("新密码和确认新密码不一致");
        }
        sysUser.setUserId(userId);
        sysUser.setPassword(passwordDTO.getPassword());
        sysUser.setUpdateTime(new Date());
        sysUser.setUpdator(CommonParam.getInstance().getUserNo());
        sysUserMapper.update(sysUser);
        return Result.success();
    }
}